package com.lry.crawlers.listener;

import com.jnewbie.JHtml;
import com.lry.crawlers.config.service.ConfigService;
import com.lry.crawlers.configuration.RabbitMQConfig;
import com.lry.crawlers.information.entity.Information;
import com.lry.crawlers.information.service.InformationService;
import com.lry.crawlers.message.service.MessageService;
import com.lry.crawlers.util.ProcessVariable;
import com.lry.crawlers.video.entity.VideoUpdate;
import com.lry.crawlers.video.entity.VideoVariable;
import com.lry.crawlers.video.mapper.VideoUpdateMapper;
import com.lry.crawlers.video.pipeline.VideoPipeline;
import com.lry.crawlers.video.processor.VideoPlusUpJProcessor;
import com.lry.crawlers.video.service.VideoChapterService;
import com.lry.crawlers.video.service.VideoUpdateService;
import com.lry.crawlers.video.service.VideoVariableService;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;

@Component
public class VideoUpdateListener {
    @Autowired
    VideoUpdateService videoUpdateService;
    @Autowired
    VideoChapterService videoChapterService;
    @Autowired
    VideoPipeline videoPipeline;
    @Autowired
    VideoVariableService videoVariableService;
    @Autowired
    InformationService informationService;
    @Autowired
    MessageService messageService;
    @Autowired
    VideoUpdateMapper videoUpdateMapper;
    @Autowired
    ConfigService configService;

    //监听update_queue队列
    @RabbitListener(queues = RabbitMQConfig.VUPDATEEQUEUE_NAME)
    public void ListenerUpdateQueue(Message message, Channel channel) throws Exception {
        String uuid =UUID.randomUUID().toString();
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        String str = new String(message.getBody());
        int i = Integer.valueOf(str.split(",")[0]);
        int m = Integer.valueOf(str.split(",")[1]);


        videoVariableService.update();

        List<VideoUpdate> videoUpdates = videoUpdateService.getVideoUpdates();
        videoUpdates = averageAssign(videoUpdates, m).get(i);
        informationService.setInformation(new Information(uuid,"视频","视频更新 - 参与更新节点数："+m+" - 当前节点临时编号："+(i+1)+" - 更新数量："+videoUpdates.size(),"进行中",0,0,new Date(),null,20));
        try {
            Thread.sleep(3000);
            //MQ应答
            channel.basicAck(deliveryTag, false);

            for(VideoVariable vv : ProcessVariable.vVariable.values()){
                List<VideoUpdate> fus = new ArrayList<>();
                for (VideoUpdate videoUpdate : videoUpdates) {
                    if(videoUpdate.getVideoVariableId()==vv.getId())
                        fus.add(videoUpdate);
                }
                if(fus==null)
                    continue;
                Map<String, Object> map = new HashMap<>();
                for (VideoUpdate fu : fus) {
                    try {
                        VideoVariable vvv = ProcessVariable.getVVariable(fu.getVideoVariableId());
                        String url = vvv.getProtocol() + "://" + vv.getUrl() + fu.getVideoUrl();
                        map.put(url.trim(), fu.getVideoId());
                    }catch (Exception e){
                        e.printStackTrace();
                        continue;
                    }
                }
                //创建请求客户端
                JHtml jHtml = new JHtml();
                jHtml.setEncoding(vv.getEncoding());
                //创建数据处理器
                VideoPlusUpJProcessor.initializeFilter();
                VideoPlusUpJProcessor videoUpJProcessor = new VideoPlusUpJProcessor(uuid,map, videoPipeline,videoChapterService,vv);
                //将客户端加入到处理器,设置开始url,设置启动线程
                videoUpJProcessor.setJHtml(jHtml)
                        .setGetMethod(vv.getMode())
                        .setUrl("https://www.baidu.com")
                        .start(configService.getOne(null).getVideoThread());
            }
            VideoPlusUpJProcessor.allUrl = 0;
            videoUpdateMapper.updateTime();
            informationService.updateInformation(new Information(uuid,new Date(),"完成",100));

        }catch (Exception e){
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw,true));
            String infomsg = sw.toString();
            channel.basicNack(deliveryTag, false, false);
            informationService.updateInformation(new Information(uuid,new Date(),"错误",10));
            messageService.setMessage(new com.lry.crawlers.message.entity.Message("视频更新出现错误！异常："+infomsg,new Date()));

        }

    }



    public static <T> List<List<T>> averageAssign(List<T> source, int n) {
        List<List<T>> result = new ArrayList<List<T>>();
        int remainder = source.size() % n;  //(先计算出余数)
        int number = source.size() / n;  //然后是商
        int offset = 0;//偏移量
        for (int i = 0; i < n; i++) {
            List<T> value = null;
            if (remainder > 0) {
                value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
                remainder--;
                offset++;
            } else {
                value = source.subList(i * number + offset, (i + 1) * number + offset);
            }
            result.add(value);
        }
        return result;
    }


}
